using System;
using System.Collections.Generic;
using System.Text;
using ALib;
using ALib.Misc;

namespace TradingPlatform.IB.TradingClient
{
    public class TradingKernel_InteractiveBrokers : TradingKernel
    {
        private InteractiverBrokers _interactiverBrokers;

        public TradingKernel_InteractiveBrokers() : base("InteractiveBrokers")
        {
        }

        public override void ConnectTradingApi()
        {
            if(_interactiverBrokers!=null)
            {
                _interactiverBrokers.Disconnect();
            }
            _interactiverBrokers = new InteractiverBrokers(TradingComm);
            _interactiverBrokers.Connect();
        }

        protected override void InitToStart()
        {
            _orderManagementDb = _interactiverBrokers.PlaceOrder.OrderManagementDb;
            _lastTicks = _interactiverBrokers.MarketData._lastTick;
            _tickSeriesList = _interactiverBrokers.MarketData._tickSeriesList;

            RequestMarketData();
        }

        protected override void Timer0_Process()
        {
            //RequestMarketData();
            //DisplayStatus("Request market data.");

            // Cancel existing orders.
            List<int> orderIdList = _interactiverBrokers.PlaceOrder.OrderManagementDb.AliveOrderIdList;
            foreach (int openOrderId in orderIdList)
            {
                _interactiverBrokers.PlaceOrder.CancelOrder(openOrderId);
            }
            DisplayStatus("Cancel existing orders.");

            // Get new order id.
            _interactiverBrokers.OrderId.RequestOrderId();
            DisplayStatus("Request order Id.");
        }

        protected override void Timer1_Process()
        {
            RequestStrategyServerAndSendOrders();

            SaveMarketData();
            DisplayStatus("Save market data.");
            _interactiverBrokers.MarketData.Clear();
            DisplayStatus("Clear market data.");
        }

        protected override void Timer2_Process()
        {
            DisplayOmsOrders(_interactiverBrokers.PlaceOrder.OrderManagementDb.OrderSetString);
            DisplayOmsOpenPosition(_interactiverBrokers.PlaceOrder.OrderManagementDb.OpenPositionString);

            // Display error messages.
            foreach (string errorMessage in _interactiverBrokers.ErrorMessageList)
            {
                DisplayErrorMessage(errorMessage);
            }
            _interactiverBrokers.ErrorMessageList.Clear();
        }

        protected override void Timer3_Process()
        {
            DisplayStatus("-----EndOfProcess-----");
        }

        protected override void RequestMarketData()
        {
            // Get market data.
            foreach (string tickerName in _tickerInfoDb.TickerNameList)
            {
                int tradingPlatformTimeZoneIndex = int.Parse(_tickerInfoDb.GetTickerInfoItem(tickerName, TickerInfoItemType.tradingPlatformTimeZoneIndex));
                int exchangeTimeZoneIndex = int.Parse(_tickerInfoDb.GetTickerInfoItem(tickerName, TickerInfoItemType.exchangeTimeZoneIndex));
                string exchange = _tickerInfoDb.GetTickerInfoItem(tickerName, TickerInfoItemType.exchange);
                string secType = _tickerInfoDb.GetTickerInfoItem(tickerName, TickerInfoItemType.secType);
                string symbol = _tickerInfoDb.GetTickerInfoItem(tickerName, TickerInfoItemType.symbol);
                string expiry = _tickerInfoDb.GetTickerInfoItem(tickerName, TickerInfoItemType.expiry);
                string currency = _tickerInfoDb.GetTickerInfoItem(tickerName, TickerInfoItemType.currency);

                int expiryIndex = int.Parse(expiry);
                int currentDateIndex = int.Parse(DateTime.Now.ToString("yyyyMM"));

                if (currentDateIndex <= expiryIndex)
                {
                    string tradingHours = _tickerInfoDb.GetTickerInfoItem(tickerName, TickerInfoItemType.tradingHours);

                    bool inTradingSessions = TradingSessionString.InTradingSession(tradingPlatformTimeZoneIndex, exchangeTimeZoneIndex, DateTime.Now, tradingHours);

                    if (inTradingSessions)
                    {
                        DisplayStatus("Subscribing market data now");
                        _interactiverBrokers.MarketData.RequestMarketData(tradingPlatformTimeZoneIndex, exchangeTimeZoneIndex, exchange, secType, symbol, expiry, currency, false);
                    }
                    else
                    {
                        DisplayStatus("Cancel market data subscription now");
                        _interactiverBrokers.MarketData.CancelMarketData(exchange, secType, symbol, expiry, currency);
                    }   
                }
            }
        }

        protected override void SendOrders(List<string> orders)
        {
            int orderId = _interactiverBrokers.OrderId._result;

            // [SendOrder],LimitOrder,2011-01-11 15:49:32.604,TraderName=Alpha,Id=3449,TickerName=Futures_HSI_201101,BuySellType=Buy,Price=23749,Quantity=1,Memo=

            foreach (string order in orders)
            {
                string strategyTickerName = order.Split(new char[] { ',' })[5].Split(new char[] { '=' })[1];
                string tickerName = _tickerInfoDb.GetTickerName(strategyTickerName);

                string exchange = _tickerInfoDb.GetTickerInfoItem(tickerName, TickerInfoItemType.exchange);
                string secType = _tickerInfoDb.GetTickerInfoItem(tickerName, TickerInfoItemType.secType);
                string symbol = _tickerInfoDb.GetTickerInfoItem(tickerName, TickerInfoItemType.symbol);
                string expiry = _tickerInfoDb.GetTickerInfoItem(tickerName, TickerInfoItemType.expiry);
                string currency = _tickerInfoDb.GetTickerInfoItem(tickerName, TickerInfoItemType.currency);

                string[] orderItems = order.Split(new char[] { ',' });
                string orderType = orderItems[1];
                int buySell = orderItems[6].Split(new char[] { '=' })[1].ToLower() == "buy" ? 1 : -1;
                double price = double.Parse(orderItems[7].Split(new char[] { '=' })[1]);
                double quantity = double.Parse(orderItems[8].Split(new char[] { '=' })[1]) * buySell;

                GoodValue.Assert(orderType == "LimitOrder" || orderType == "MarketOrder");

                if (orderType == "LimitOrder")
                {
                    _interactiverBrokers.PlaceOrder.RequestToPlaceLimitOrder(exchange, secType, symbol, expiry, currency, orderId++, price, (int)quantity);
                }
                if (orderType == "MarketOrder")
                {
                    _interactiverBrokers.PlaceOrder.RequestToPlaceMarketOrder(exchange, secType, symbol, expiry, currency, orderId++, (int)quantity);
                }
            }
        }

        public override void Dispose()
        {
            if (_interactiverBrokers != null)
            {
                _interactiverBrokers.Close();
            }
        }

        protected override SortedList<string, string> GetStrategyTickerNameList(List<string> tickerNameList)
        {
            SortedList<string, string> strategyTickerNameList = new SortedList<string, string>();

            foreach (string tickerName in tickerNameList)
            {
                string strategyTickerName = GetStrategyTickerName(tickerName);
                strategyTickerNameList.Add(tickerName, strategyTickerName);
            }
            return strategyTickerNameList;
        }

        private string GetStrategyTickerName(string tickerName)
        {
            // Futures,TY,202012
            string result = string.Empty;
            string secType = _tickerInfoDb.GetTickerInfoItem(tickerName, TickerInfoItemType.secType);
            if (secType == SecType.FUT.ToString())
            {
                string strategySymbol = _tickerInfoDb.GetTickerInfoItem(tickerName, TickerInfoItemType.strategySymbol);
                string strategyExpiry = _tickerInfoDb.GetTickerInfoItem(tickerName, TickerInfoItemType.expiry);
                result = string.Format(@"Futures,{0},{1}", strategySymbol, strategyExpiry);
            }

            GoodValue.Assert(result != string.Empty);
            return result;
        }

        public override void UpdateMarketBidAsk(MarketDataBestLevelMessage msg)
        {
            _interactiverBrokers.MarketData.UpdateBidAsk(msg);
        }

        public override void UpdateMarketTraded(MarketDataTradeMessage msg)
        {
            _interactiverBrokers.MarketData.UpdateTraded(msg);
        }

        public override void UpdateOrderStatus(OrderStatusMessage msg)
        {
            _interactiverBrokers.PlaceOrder.UpdateOrder(msg);
        }
    }
}